﻿using System;
using System.IO;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using ESoft.Core.Data.Service;
using ESoft.Core.Util.Helpers;
using ESoft.Core.Utils.Extensions;
using ESoft.Core.Web.Common.Filters;
using ESoft.Core.Web.VO;
using ESoft.Portal.Data.Domain.Entity;
using ImageMagick;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;

namespace ESoft.Portal.Controllers
{
    [Route("/api/Image")]
    public class ImageController : ControllerBase
    {
        private readonly string _baseImageDir;
        private readonly IBaseService _baseService;
        private readonly IMemoryCache _memoryCache;
        private readonly IHostingEnvironment _hostingEnvironment;
        public ImageController(IConfiguration configuration, IBaseService baseService, IMemoryCache memoryCache, IHostingEnvironment hostingEnvironment)
        {
    
            this._baseService = baseService;
            _memoryCache = memoryCache;
            _hostingEnvironment = hostingEnvironment;
            _baseImageDir = hostingEnvironment.WebRootPath + configuration.GetSection("BASE_IMAGE_DIR").Value;
        }

        [HttpPost("upload")]
        //[DisableRequestSizeLimit] //禁用http限制大小
        [RequestSizeLimit(100 * 1024 * 1024)] //限制http大小
        public object Post(IFormFile file)
        {
            if (file.IsNull())
                return null;
            String tempPath = DateTime.Now.ToString("yyyy-MM-dd");
            string saveDir = Path.Combine(Directory.GetCurrentDirectory(), _baseImageDir, tempPath);
            if (!Directory.Exists(saveDir))
                Directory.CreateDirectory(saveDir);
            var fileName = ContentDispositionHeaderValue
                              .Parse(file.ContentDisposition)
                              .FileName
                              .Trim('"');
            var newFileName = Path.GetFileNameWithoutExtension(fileName) + "_" + DateTime.Now.ToString("yyyyMMddHHmmss")
                + new Random().Next(1000, 90000) + Path.GetExtension(fileName);
            var tempFullPath = Path.Combine(tempPath, $@"{newFileName}");
            var savePath = Path.Combine(_baseImageDir, tempFullPath);
            using (var fs = new FileStream(savePath, FileMode.Create))
            {
                file.CopyTo(fs);
                fs.Position = 0;
                var optimizer = new ImageOptimizer();
                optimizer.LosslessCompress(fs);
                fs.Flush();
            }

            var image = new CImageEntity
            {
                ImageName = fileName,
                ImageId = StringHelper.GetId(),
                ImagePath = tempFullPath,
                ImageExe = Path.GetExtension(fileName),
                CreateDatetime = DateTime.Now,
                MineType = file.ContentType
            };
            _baseService.Add(image);

            return image;
        }


        [HttpPost("upload4layedit")]
        [RequestSizeLimit(800 * 1024)] //限制http大小
        public object Post4LayEdit(IFormFile imgFile)
        {
            if (imgFile.IsNull())
                return null;
            String tempPath = DateTime.Now.ToString("yyyy-MM-dd");
            string saveDir = Path.Combine(Directory.GetCurrentDirectory(), _baseImageDir, tempPath);
            if (!Directory.Exists(saveDir))
                Directory.CreateDirectory(saveDir);
            var fileName = ContentDispositionHeaderValue
                              .Parse(imgFile.ContentDisposition)
                              .FileName
                              .Trim('"');
            var newFileName = Path.GetFileNameWithoutExtension(fileName) + "_" + DateTime.Now.ToString("yyyyMMddHHmmss")
                + new Random().Next(1000, 90000) + Path.GetExtension(fileName);
            var tempFullPath = Path.Combine(tempPath, $@"{newFileName}");
            var savePath = Path.Combine(_baseImageDir, tempFullPath);
            using (var fs = new FileStream(savePath, FileMode.Create))
            {
                imgFile.CopyTo(fs);
                fs.Position = 0;
                var optimizer = new ImageOptimizer();
                optimizer.LosslessCompress(fs);
                fs.Flush();
            }

            var image = new CImageEntity
            {
                ImageName = fileName,
                ImageId = StringHelper.GetId(),
                ImagePath = tempFullPath,
                ImageExe = Path.GetExtension(fileName),
                CreateDatetime = DateTime.Now,
                MineType = imgFile.ContentType
            };
            _baseService.Add(image);

            dynamic dob = new System.Dynamic.ExpandoObject();
            dob.error = 0;
            dob.msg = "";
            dob.data = new System.Dynamic.ExpandoObject();
            dob.url = "/api/Image/download/" + image.ImageId ;
            dob.data.title = image.ImageName;

            return dob;
        }

        [SkipUserAuthorize]
        [HttpGet("download/{imageId}")]
        public async Task<IActionResult> Get(string imageId, [FromQuery]int width = 0, [FromQuery]int height = 0)
        {
            if (!_memoryCache.TryGetValue<CImageEntity>("CImageEntity-" + imageId, out var fileEntity))
            {
                fileEntity = this._baseService.Find<CImageEntity>(imageId);
                _memoryCache.Set("CImageEntity-" + imageId, fileEntity);
            }

            if (fileEntity != null)
            {
                var addrUrl = Path.Combine(Directory.GetCurrentDirectory(), _baseImageDir, fileEntity.ImagePath);
                if (!System.IO.File.Exists(addrUrl))
                {
                    return NotFound();
                }
                if (width > 0 && height > 0)
                {
                    string path = ImageHelper.GenerateHighThumbnail(addrUrl, width, height);
                    var b = await System.IO.File.ReadAllBytesAsync(path);
                    return File(b, fileEntity.MineType);
                }
                else
                {
                    var b = await System.IO.File.ReadAllBytesAsync(addrUrl);
                    return File(b, fileEntity.MineType);
                }
            }

            return NotFound();
        }

        [HttpGet("CompressImages")]
        public void CompressImages()
        {
            DirectoryInfo dir = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), _baseImageDir));
            FindFileAnCompress(dir);
        }

        static void FindFileAnCompress(DirectoryInfo di)
        {
            FileInfo[] fis = di.GetFiles();
            foreach (var file in fis)
            {
                var optimizer = new ImageOptimizer();
                optimizer.LosslessCompress(file);
                file.Refresh();
            }
            DirectoryInfo[] dis = di.GetDirectories();
            foreach (var dir in dis)
            {
                FindFileAnCompress(dir);
            }
        }
        [HttpDelete("delete/{imageId}")]
        public Object Delete(string imageId)
        {
            CImageEntity imageEntity = this._baseService.Find<CImageEntity>(imageId);
            if (imageEntity.IsNotNull())
            {
                var addrUrl = Path.Combine(Directory.GetCurrentDirectory(), _baseImageDir, imageEntity.ImagePath);
                if (System.IO.File.Exists(addrUrl))
                {
                    System.IO.File.Delete(addrUrl);
                }
                this._baseService.Delete(imageEntity);
                return ResponseResult.Success();
            }
            return ResponseResult.FailOut("不存在该文件！");
        }
    }
}
